package org.wak.dialog.custom
{
	import flash.display.DisplayObject;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	
	import org.wak.character.AdventureCharacter;
	import org.wak.character.display.AnimationBehaviour;
	import org.wak.dialog.AdventureDialog;
	import org.wak.dialog.DialogManager;
	import org.wak.dialog.IDialogsController;
	import org.wak.dialog.SayItem;
	import org.wak.dialog.Topic;
	import org.wak.dialog.TopicActions;
	import org.wak.dialog.event.PuzzleActionEvent;
	import org.wak.dialog.event.TextSelectedEvent;
	import org.wak.dialog.scumm.DialogMenu;
	import org.wak.dialog.scumm.DialogTextDisplay;
	import org.wak.gui.GuiManager;
	import org.wak.gui.custom.CustomGui;
	import org.wak.main.AdventureMaster;
	import org.wak.scene.SceneManager;
	import org.wak.utils.IIterator;
	import org.wak.utils.Utils;
	import org.wak.utils.WakSimpleButton;


	/**
	 * Custom style Dialog controller. 
	 * 
	 */
	public class CustomDialogController extends Sprite implements IDialogsController
	{
		protected var mDialogLayer:Sprite = null ;
		
		// local reference to the gui manager.
		protected var mGuiMngr:GuiManager = null ;
		
		// local reference to the scene manager
		protected var mSceneMngr:SceneManager = null ;
		
		// local reference to the dialog manager
		protected var mDialogMngr:DialogManager = null ;
		
		// local reference to the resources.
		protected var mResourceManager:Class = null ;
		
		protected var mStageWidth:Number = 0 ;
		protected var mStageHeight:Number = 0 ;
		
		protected var mBackPanel:DisplayObject = null ;
		protected var mMask:Shape = null ;
		
		protected const kPanelHPercent:Number = 27.5 ;
		
		protected var mDialogsMenuArray:Array = null ;
		
		
		// modern gui
		protected var mCustomGui:CustomGui = null ;
		
		// current menu dialog
		protected var mCurrentDialogMenu:DialogMenu = null ;
		
		// previous menu dialog
		protected var mPreviousDialogMenu:DialogMenu = null ;
		
		// last dialog started with StartDialog
		protected var mCurrentDialog:AdventureDialog = null ;
		
		// previous last dialog started with StartDialog
		protected var mPreviousDialog:AdventureDialog = null ;
		
		// Local copy of the player's character id
		protected var mPlayerCharId:String = "" ;
		
		// the current playing topic
		protected var mPlayingTopic:Topic = null ;
		
		// settings loaded vars.//
		
		// text delay when a char speaks.
		protected var mTextSpeedFactor:Number = 60 ;
		
		// width of a text option.
		protected var mTextOptionWidth:int  = 100 ;
		
		// height of a text option.
		protected var mTextOptionHeight:int  = 30 ;
		
		// vertical dialog offset to display text.
		protected var mTextHeadDistance:int = 0 ;
		
		// scroll up button
		protected var mScrollUpBtn:WakSimpleButton = null;
		
		// scroll down button.
		protected var mScrollDownBtn:WakSimpleButton = null;
		
		// vars of style for the spoken text.
		protected var mSpokenTextFont:String = "acknowtt" ;
		protected var mSpokenTextSize:Number = 13 ;
		protected var mSpokenTextBold:Boolean = true ;
		protected var mSpokenTextUseEmbedFont:Boolean = true ;
		
		// Y coordinate for the dialog menus.
		protected var mDMenusY:Number = -1 ;
		
		protected var mMenuOffsetX:Number = 0 ;
		protected var mMenuOffsetY:Number = 0 ;
		
		protected var mMaskShrink:Number  = 0;
		
		protected var mDisplayInfoY:Number = 0 ;
		protected var mDisplayInfoColor:uint = 0xFFFFFF ;
		
		//vars of style for the text on dialogs menu.
		protected var mMenuTextFont:String = "acknowtt" ;
		protected var mMenuTextColor:uint = 0xFFFFFF ;
		protected var mMenuTextColorOver:uint = 0xFF00FF ;
		protected var mMenuTextSize:Number = 13 ;
		protected var mMenuTextBold:Boolean = true ;
		protected var mMenuTextUseEmbedFont:Boolean = true ;
		
		
		////////////////////////
		
		
		
		/**
		 * Constructor 
		 * @param pLayer Sprite of the dialog layers of the adventure. 
		 * @param pSettings XML with the settings for the dialogs.
		 * 
		 */		
		public function CustomDialogController(pLayer:Sprite, pSettings:XML)
		{
			super();
			mResourceManager = AdventureMaster.Resources ;
			mDialogLayer = pLayer ;
			mDialogsMenuArray = new Array();
			mCustomGui = AdventureMaster.GuiMngr.adventureGui as CustomGui ;
			
			LoadSettings(pSettings);
			
			if(mScrollUpBtn == null)
				mScrollUpBtn = CreateUpArrow() ;
				
			if(mScrollDownBtn == null)
				mScrollDownBtn = CreateDownArrow() ;
			
		}
		
		/**
		 * @inheritDoc
		 */	
		public function Initialize():void
		{
			mGuiMngr = AdventureMaster.GuiMngr ;
			mSceneMngr = AdventureMaster.SceneMngr ;
			mDialogMngr = AdventureMaster.DialogMngr ;
			
			mStageWidth = mDialogLayer.stage.stageWidth ;
			mStageHeight = mDialogLayer.stage.stageHeight ;
			
			
			mPlayerCharId = AdventureMaster.defaultPlayerCharacterId ;
			
			this.addEventListener(Event.ADDED_TO_STAGE,OnAddedToStage);
		}
		
		/**
		 * @inheritDoc
		 */	
		public function get display():DisplayObject
		{
			return this ;
		}
		
		/**
		 * @inheritDoc
		 */	
		public function StartDialog(pDialog:AdventureDialog):void
		{
			//Set default cursor
			mCustomGui.ChangeMouseCursorTo( CustomGui.NormalMouseCursor );
			mCustomGui.SetMouseInfoText("");
			mCustomGui.SetInfoBoxText(" ");
			
			//trace("modern StartDialog");
			if(mCurrentDialog != null)
			{
				mCurrentDialogMenu.removeEventListener( DialogMenu.TEXT_SELECTED, OnDialogOptionSelected );
				if(this.contains( mCurrentDialogMenu) )
					this.removeChild(mCurrentDialogMenu);				
			}
			
			
			mGuiMngr.enabled = false ;
			mSceneMngr.enabled = false ;
			
			mPreviousDialog = mCurrentDialog ;
			mCurrentDialog = pDialog ;
			
			// if the entry topic is just for one time only.
			if(mCurrentDialog.startupTopic.onlyOnce)
			{ 
				if(!mCurrentDialog.startupTopic.played)
				{
					PlayTopic(mCurrentDialog.startupTopic,OnEntryTopicSayCompleted );
				}
				else
				{
					if(mCurrentDialog.isPresent( mPlayerCharId ))
						OnEntryTopicSayCompleted();
					else
						StopDialog();
				}
			}
			else
			{
				PlayTopic(mCurrentDialog.startupTopic,OnEntryTopicSayCompleted );
			}
		}
		
		/**
		 * @private
		 */
		protected function StartDialogAfterEntryTopic():void
		{
			//var fDialogMenu:DialogMenu = mDialogsMenuArray[mCurrentDialog.dialogId] as DialogMenu;
			/*
			
			if(fDialogMenu == null)
			{
				fDialogMenu = new DialogMenu(mCurrentDialog, mTextOptionWidth, mTextOptionHeight,
					  mMenuTextFont,mMenuTextColor,mMenuTextColorOver,mMenuTextSize,mMenuTextBold, mMenuTextUseEmbedFont);
				
				mDialogsMenuArray[mCurrentDialog.dialogId] = fDialogMenu ;
				fDialogMenu.x = mBackPanel.x + mScrollUpBtn.width + mMenuOffsetX ;
				fDialogMenu.y = mBackPanel.y + mMenuOffsetY;
			}
			*/
			
			if(mCurrentDialog == null)
				return ;
			
			
			var fDialogMenu:DialogMenu = CreateDialogMenu(mCurrentDialog.dialogId);
			
			mPreviousDialogMenu = mCurrentDialogMenu ;
			mCurrentDialogMenu = fDialogMenu ;
			mCurrentDialogMenu.addEventListener( DialogMenu.TEXT_SELECTED, OnDialogOptionSelected );
			mCurrentDialogMenu.mask = mMask ;
			
			mBackPanel.visible = true ;
			// Add the dialog panel.
			this.addChild(mScrollUpBtn);
			this.addChild(mScrollDownBtn);
			this.addChild(mCurrentDialogMenu);
			
			mScrollDownBtn.addEventListener(MouseEvent.MOUSE_UP,OnScrollDown);
			mScrollUpBtn.addEventListener(MouseEvent.MOUSE_UP,OnScrollUp);
			
			SetDialogPanelVisible(true);
			UpdateScrollButtons();
			
		}
		
		protected function CreateDialogMenu(pDialogId:String):DialogMenu
		{
			var fDialogMenu:DialogMenu = mDialogsMenuArray[pDialogId] as DialogMenu;
			var fAdvDialog:AdventureDialog = mDialogMngr.GetDialog(pDialogId);
			
			if((fDialogMenu == null) && (fAdvDialog != null))
			{
				fDialogMenu = new DialogMenu(fAdvDialog, mTextOptionWidth, mTextOptionHeight,
					  mMenuTextFont,mMenuTextColor,mMenuTextColorOver,mMenuTextSize,mMenuTextBold, mMenuTextUseEmbedFont);
				
				mDialogsMenuArray[pDialogId] = fDialogMenu ;
				fDialogMenu.x = mBackPanel.x + mScrollUpBtn.width + mMenuOffsetX ;
				fDialogMenu.y = mBackPanel.y + mMenuOffsetY;
			}
			return fDialogMenu ;
		}
		
		
		/**
		 * Load the settings of the dialogs using the parameters in pSettings 
		 * @param pSettings XML with the settings.
		 * 
		 */		
		protected function LoadSettings( pSettings:XML ):void
		{
			mTextSpeedFactor = pSettings.TextDelay ;
		
			if(pSettings.Background != "")
			{
				var fId:String = pSettings.Background ;
				mBackPanel = new mResourceManager[fId] ;
			}
			
			mTextOptionWidth  = pSettings.TextOptionWidth ;
			
			mTextOptionHeight  = pSettings.TextOptionHeight ;
			
			mTextHeadDistance = pSettings.TextHeadDistance ;
			
			// Y of the display info.
			if( pSettings.DisplayInfoY != "")
			{
				mDisplayInfoY = pSettings.DisplayInfoY ;
			}
			// color of the display info text.
			if( pSettings.DisplayInfoColor != "")
			{
				mDisplayInfoColor = uint("0x"+pSettings.DisplayInfoColor) ;
			}
			
			if( pSettings.DialogMenuY != "")
			{
				mDMenusY = pSettings.DialogMenuY ;
			}
			
			if( pSettings.MaskShrink != "")
			{
				mMaskShrink = pSettings.MaskShrink ;
			}
			
			if( pSettings.DialogMenuOffsetX != "" )
			{
				mMenuOffsetX = pSettings.DialogMenuOffsetX ;
			}
			if( pSettings.DialogMenuOffsetY != "" )
			{
				mMenuOffsetY = pSettings.DialogMenuOffsetY ;
			}
			
			if( pSettings.SpeakText.TextFont != "" )
				mSpokenTextFont = pSettings.SpeakText.TextFont ;
			mSpokenTextSize = pSettings.SpeakText.TextSize ;
			mSpokenTextBold = pSettings.SpeakText.Bold == "true" ? true : false ;
			mSpokenTextUseEmbedFont = pSettings.SpeakText.UseEmbedFont == "true" ? true : false ;
			
			if( pSettings.DialogMenuText.TextFont != "" )
				mMenuTextFont = pSettings.DialogMenuText.TextFont ;
			mMenuTextColor = uint("0x"+pSettings.DialogMenuText.FontColor) ;
			mMenuTextColorOver = uint("0x"+pSettings.DialogMenuText.FontOverColor) ;
			mMenuTextSize = pSettings.DialogMenuText.TextSize ;
			mMenuTextBold = pSettings.DialogMenuText.Bold == "true" ? true : false ; ;
			mMenuTextUseEmbedFont = pSettings.DialogMenuText.UseEmbedFont == "true" ? true : false ; ;
			
			
			// Load the scrolling buttons
			var fNewBtn:WakSimpleButton = null ;
			var fOver:DisplayObject = null ;
			var fUp:DisplayObject = null ;
			var fDown:DisplayObject = null ;
			for each( var btn:XML in pSettings.Button)
			{
				if((btn.Up != "") && (btn.Over != "") && (btn.Down != "") )
				{
					fUp = new mResourceManager[btn.Up] as DisplayObject;
					fOver = new mResourceManager[btn.Over] as DisplayObject;
					fDown = new mResourceManager[btn.Down] as DisplayObject;
					fNewBtn= new WakSimpleButton(fUp,fOver,fDown);
					if(btn.@id == "ScrollUp")
					{
						mScrollUpBtn = fNewBtn ;
					}
					else if(btn.@id == "ScrollDown")
					{
						mScrollDownBtn = fNewBtn ;
					}
				}
			}
		
		}
		
		/**
		 * Force to stop any dialog playing. 
		 * 
		 */		
		protected function StopDialog():void
		{
			if(mCurrentDialogMenu != null)
			{
				if( this.contains(mCurrentDialogMenu) )
					this.removeChild(mCurrentDialogMenu);
			}
				
			if(this.contains(mScrollDownBtn))	
				this.removeChild(mScrollDownBtn);
			if(this.contains(mScrollUpBtn) )
				this.removeChild(mScrollUpBtn);
			
			mScrollDownBtn.removeEventListener(MouseEvent.MOUSE_UP,OnScrollDown);
			mScrollUpBtn.removeEventListener(MouseEvent.MOUSE_UP,OnScrollUp);
			
			mBackPanel.visible = false ;
			
			mCurrentDialog = null ;
			mGuiMngr.enabled = true ;
			mSceneMngr.enabled = true ;
		}
		
		/**
		 * @private
		 */
		protected function OnEntryTopicSayCompleted():void
		{
			if(!(mCurrentSayIterator.hasNext()))
			{
				RunAction(mPlayingTopic);
				mPlayingTopic = null ;
				StartDialogAfterEntryTopic();
				return ;
			}
			var fSayItem:SayItem = mCurrentSayIterator.next() as SayItem ;
			var fSpeakerChar:AdventureCharacter = AdventureMaster.CharactersMngr.GetCharacter(fSayItem.speakerId) ;
			CharacterSay(fSpeakerChar, fSayItem.text, OnEntryTopicSayCompleted ); 
			
		}
		
		/**
		 * @private
		 */
		protected function OnDialogOptionSelected(event:TextSelectedEvent):void
		{
			var fTopic:Topic = event.topic ;
			PlayTopic(fTopic, OnTopicSayCompleted);
		}
		
		protected var mCurrentSayIterator:IIterator = null ;
		
		/**
		 * Start to play a dialog topic. 
		 * @param pTopic the topic to play
		 * @param pOnCompleteFunc callaback function called when the topic finish.
		 * 
		 */		
		public function PlayTopic(pTopic:Topic, pOnCompleteFunc:Function):void
		{
			//trace("modern PlayTopic");
			mCurrentSayIterator = pTopic.GetSayItems() ;
			
			if(!(mCurrentSayIterator.hasNext()))
				return ;
			
			mPlayingTopic = pTopic ;	
			SetDialogPanelVisible(false);
			
			var fSayItem:SayItem = mCurrentSayIterator.next() as SayItem;
			var fSpeakerChar:AdventureCharacter = null ; 
			
			mBackPanel.visible = false ;
			pTopic.played = true ;
			
			if(fSayItem.speakerId == mPlayerCharId)
			{
				if( pTopic.say )
				{
					fSpeakerChar = AdventureMaster.CharactersMngr.GetCharacter(fSayItem.speakerId) ;
					CharacterSay(fSpeakerChar, fSayItem.text, pOnCompleteFunc );
				}
				else
				{
					if(!(mCurrentSayIterator.hasNext()))
					{
						RunAction(pTopic);
						return ;
					}
						
					fSayItem = mCurrentSayIterator.next() as SayItem;
					fSpeakerChar = AdventureMaster.CharactersMngr.GetCharacter(fSayItem.speakerId) ;
					CharacterSay(fSpeakerChar, fSayItem.text, pOnCompleteFunc );
				}
			}
			else
			{
				fSpeakerChar = AdventureMaster.CharactersMngr.GetCharacter(fSayItem.speakerId) ;
				CharacterSay(fSpeakerChar, fSayItem.text, pOnCompleteFunc );
			}
			
		}
		
		/**
		 * @private
		 */
		protected function OnTopicSayCompleted():void
		{
			if(!(mCurrentSayIterator.hasNext()))
			{
				SetDialogPanelVisible(true) ;
				RunAction(mPlayingTopic);
				mPlayingTopic = null ;
				return ;
			}
			var fSayItem:SayItem = mCurrentSayIterator.next() as SayItem ;
			var fSpeakerChar:AdventureCharacter = AdventureMaster.CharactersMngr.GetCharacter(fSayItem.speakerId) ;
			CharacterSay(fSpeakerChar, fSayItem.text, OnTopicSayCompleted ); 
			
		}
		
		/**
		 * @private
		 */
		protected function RunAction(pTopic:Topic):void
		{
			if(pTopic == null)
				return ;
				
			switch( pTopic.action )
			{
				case TopicActions.EXIT:
					StopDialog();
				break;
				case TopicActions.GOTO:	
					GotoDialog( pTopic.target )
				break;
				case TopicActions.BACK:
					GoBackDialog();
				break;
				case TopicActions.ACTIVATE:
					ActivateOption(pTopic.target);
				break;
				case TopicActions.ACTION:
					RunTopicAction(pTopic.target);
				break;
			
			}
		}
	
		/**
		 * @private
		 */	
		protected function RunTopicAction( pFuncName:String ):void
		{
			var fEvent:Event = new PuzzleActionEvent( PuzzleActionEvent.PUZZLE_ACTION_EVENT, pFuncName);
			this.dispatchEvent(fEvent);
		}
	
		/**
		 * @inheritDoc
		 */	
		public function ActivateOption(pTopicId:String):void
		{
			mCurrentDialogMenu.ActivateOption(pTopicId);
		}
		
		/**
		 * @private
		 */
		protected function GoBackDialog():void
		{
			if( mPreviousDialog == null )
				return ;
			
			if(mCurrentDialog != null)
			{
				mCurrentDialogMenu.removeEventListener( DialogMenu.TEXT_SELECTED, OnDialogOptionSelected );
				if(this.contains( mCurrentDialogMenu) )
					this.removeChild(mCurrentDialogMenu);				
			}
				
			//StartDialog(mPreviousDialog);
			var fBackDialog:AdventureDialog = mPreviousDialog ;
			
			mPreviousDialog = mCurrentDialog ;
			mCurrentDialog = fBackDialog ;
			
			StartDialogAfterEntryTopic();
		}
		
		/**
		 * @private
		 */
		protected function GotoDialog(pDialogId:String):void
		{
			var fDialog:AdventureDialog = mDialogMngr.GetDialog( pDialogId );
			StartDialog(fDialog);
		}
		
		/**
		 * @private
		 */		
		protected function SetDialogPanelVisible(value:Boolean):void
		{
			
			if(mCurrentDialogMenu != null)
			{
				mCurrentDialogMenu.visible = value ;
				mScrollDownBtn.visible = value ;
				mScrollUpBtn.visible = value ;
				mBackPanel.visible = value ;
			}
			
		}
		
		protected var mOnCharacterSayCompleted:Function = null ;
		
		/**
		 * Makes a character say something.
		 * @param pChar The speaker character.
		 * @param pTextToSay The text that the character will way.
		 * @param pOnComplete Callback function called when the character finished to talk.
		 * 
		 */		
		public function CharacterSay(pChar:AdventureCharacter, pTextToSay:String, pOnComplete:Function = null):void
		{
			//trace("CharacterSay:"+pTextToSay)
			var fNewText:DialogTextDisplay = new DialogTextDisplay(pTextToSay,GetTextTime(pTextToSay),
											mDialogLayer, pChar.characterDisplay,mSpokenTextFont,
											mSpokenTextSize,pChar.speechColor,mSpokenTextBold, mSpokenTextUseEmbedFont);
			mOnCharacterSayCompleted = pOnComplete ;
			
			fNewText.x = pChar.characterDisplay.dialogX ;
			fNewText.y = pChar.characterDisplay.dialogY - mTextHeadDistance;
			fNewText.addEventListener(Event.COMPLETE,OnTextDisplayCompleted,false,0,true);
			fNewText.clickEndEnabled = true ;
			mDialogLayer.addChild(fNewText);
			
			var fTalkBehaviour:String = GetTalkAnim(pChar.characterDisplay.currentBehaviour);
			//trace("fTalkBehaviour:"+fTalkBehaviour);
			// start the talk animation.
			if( fTalkBehaviour != "")
				pChar.characterDisplay.SetAnimBehaviour(fTalkBehaviour,-1);
		}
		
		/**
		 * @private 
		 */
		protected function OnMouseMove(event:MouseEvent):void
		{
			mScrollDownBtn.Update(event.stageX, event.stageY);
			mScrollUpBtn.Update(event.stageX, event.stageY);
		}
		
		/**
		 * @private 
		 */
		public function UpdateScrollButtons():void
		{
			if(mCurrentDialogMenu == null)
				return ;
			//trace("UpdateScrollButtons: " + (mCurrentDialogMenu.y + mCurrentDialogMenu.height ) + "  - " +(mBackPanel.y + mBackPanel.height));
			if( (mCurrentDialogMenu.y + mCurrentDialogMenu.height ) > (mBackPanel.y + mBackPanel.height  ) )
			{
				mScrollDownBtn.enabled = true ;
			} 
			else
			{
				mScrollDownBtn.enabled = false ;
			}
			
			if( mCurrentDialogMenu.y < mBackPanel.y )
			{
				mScrollUpBtn.enabled = true ;
			}
			else
			{
				mScrollUpBtn.enabled = false ;
			}
		}
		
		/**
		 * @private 
		 */
		protected function OnTextDisplayCompleted(event:Event):void
		{
			//trace("OnTextDisplayCompleted");
			var fTextDisplay:DialogTextDisplay = event.target as DialogTextDisplay ;
			
			if( fTextDisplay == null)
				return ;
				
			fTextDisplay.removeEventListener(Event.COMPLETE,OnTextDisplayCompleted);
			
			if(fTextDisplay.speakerDisplay == null)
				return ;
			
			var fRestoreAnim:String = GetReverseTalkAnim(fTextDisplay.speakerDisplay.currentBehaviour);
			
			if(fRestoreAnim != "")
				fTextDisplay.speakerDisplay.SetAnimBehaviour(fRestoreAnim);
				
			if(mOnCharacterSayCompleted != null)
				mOnCharacterSayCompleted();
		
		}
		
		/**
		 * @private 
		 */
		protected function GetTalkAnim(pCurrentBehaviour:String):String
		{
			var fAnim:String = "" ;
			switch(pCurrentBehaviour)
			{
				case AnimationBehaviour.STANDING_FRONT:
					fAnim = AnimationBehaviour.TALK_FRONT ;
				break ;
				case AnimationBehaviour.STANDING_BACK:
					fAnim = AnimationBehaviour.TALK_BACK ;
				break ;
				case AnimationBehaviour.STANDING_LEFT:
					fAnim = AnimationBehaviour.TALK_LEFT ;
				break ;
				case AnimationBehaviour.STANDING_RIGHT:
					fAnim = AnimationBehaviour.TALK_RIGHT ;
				break ;
				
			}
			
			return fAnim ;
		}
		
		/**
		 * @private 
		 */
		protected function GetReverseTalkAnim(pCurrentBehaviour:String):String
		{
			var fAnim:String = "" ;
			switch(pCurrentBehaviour)
			{
				case AnimationBehaviour.TALK_FRONT:
					fAnim = AnimationBehaviour.STANDING_FRONT ;
				break ;
				case AnimationBehaviour.TALK_BACK:
					fAnim = AnimationBehaviour.STANDING_BACK ;
				break ;
				case AnimationBehaviour.TALK_LEFT:
					fAnim = AnimationBehaviour.STANDING_LEFT ;
				break ;
				case AnimationBehaviour.TALK_RIGHT:
					fAnim = AnimationBehaviour.STANDING_RIGHT;
				break ;
				
			}
			
			return fAnim ;
		}
		
		/**
		 * @private 
		 */
		protected function GetTextTime(pText:String):int
		{
			var fWords:int = WordCount( pText );
			
			var fTextSpeed:Number = mTextSpeedFactor ;
			if(fWords <= 4)
				fTextSpeed *= 3 ;
			
			var fTime:int =  pText.length * fTextSpeed ;
			//trace("GetTextTime:"+ fTime)
			return fTime ;
		}
		
		/**
		 * @private 
		 */
		protected function WordCount(pText:String):int
		{
			var fTotal:int = 0 ;
			var fChar:String = "" ;
			
			for( var i:int = 0; i < pText.length; i++)
			{
				if( pText.charAt(i) == " " )
					fTotal++ ; 
			}
			return fTotal ;
		
		}
		
		/**
		 * @private 
		 */
		protected function OnAddedToStage(event:Event):void
		{
			this.removeEventListener(Event.ADDED_TO_STAGE,OnAddedToStage);
			
			// the gui panel usually is the 27.5 % of the screen height.
			var fPanelH:Number = kPanelHPercent * mStageHeight / 100 ;
			
			if(mBackPanel == null)
			{
				var fBack:Sprite = new Sprite();
				fBack.graphics.beginFill(0x000000,1);
				fBack.graphics.drawRect(0,0,mStageWidth,fPanelH);
				fBack.graphics.endFill();
				
				mBackPanel = fBack ;
			}
			mBackPanel.x = Utils.AlignCenter(mBackPanel.width, mStageWidth);
			
			mMask = new Shape();
			mMask.graphics.beginFill(0x000000,1);
			mMask.graphics.drawRect(0,0,mBackPanel.width + mMaskShrink ,mBackPanel.height + mMaskShrink);
			mMask.graphics.endFill();
			
			if(mDMenusY == -1 )
			{
				mBackPanel.y = stage.stageHeight/2 - mBackPanel.height/2 ;
			}
			else
			{
				mBackPanel.y = stage.stageHeight/2 - mBackPanel.height/2 ;
			}
			mMask.x = mBackPanel.x + (mMaskShrink/2);
			mMask.y = mBackPanel.y + (mMaskShrink/2);
			
			mScrollUpBtn.y = mBackPanel.y + 2;
			mScrollUpBtn.x = mBackPanel.x + 2 ;
			mScrollDownBtn.y = mBackPanel.y + mBackPanel.height - mScrollDownBtn.height - 2;
			mScrollDownBtn.x = mBackPanel.x +2 ;
			
			// add the back panel
			this.addChild( mBackPanel );
			//this.mask = mMask ;
			mBackPanel.visible = false ;
			
			//this.addEventListener(MouseEvent.MOUSE_MOVE,OnMouseMove);
			this.addEventListener(Event.REMOVED_FROM_STAGE,OnRemovedFromStage);
			stage.addEventListener(Event.RESIZE, resized);
			mScrollDownBtn.addEventListener(MouseEvent.MOUSE_UP,OnScrollDown);
			mScrollUpBtn.addEventListener(MouseEvent.MOUSE_UP,OnScrollUp);
		}
		
		private function resized(e:Event):void
		{
			mBackPanel.x = Utils.AlignCenter(mBackPanel.width, stage.stageWidth);
			mBackPanel.y = stage.stageHeight/2 - mBackPanel.height/2 ;
			mScrollUpBtn.y = mBackPanel.y + 2;
			mScrollUpBtn.x = mBackPanel.x + 2 ;
			mScrollDownBtn.y = mBackPanel.y + mBackPanel.height - mScrollDownBtn.height - 2;
			mScrollDownBtn.x = mBackPanel.x +2 ;
			mMask.x = mBackPanel.x + (mMaskShrink/2);
			mMask.y = mBackPanel.y + (mMaskShrink/2);
		}
		
		/**
		 * @private 
		 */
		protected function OnRemovedFromStage(event:Event):void
		{
			
			this.addEventListener(Event.ADDED_TO_STAGE,OnAddedToStage);
			
			mScrollDownBtn.removeEventListener(MouseEvent.MOUSE_UP,OnScrollDown);
			mScrollUpBtn.removeEventListener(MouseEvent.MOUSE_UP,OnScrollUp);
			
			this.removeEventListener(Event.REMOVED_FROM_STAGE,OnRemovedFromStage);
			//this.removeEventListener(MouseEvent.MOUSE_MOVE,OnMouseMove);
		}
		
		/**
		 * @private 
		 */
		protected function OnScrollUp(event:Event):void
		{
			if(!mScrollUpBtn.enabled)
				return ;
				
			mCurrentDialogMenu.y += (mCurrentDialogMenu.optionHeight + mCurrentDialogMenu.separatorY + mMenuOffsetY);
			UpdateScrollButtons();
		}
		
				/**
		 * @private 
		 */
		protected function OnScrollDown(event:Event):void
		{
			if(!mScrollDownBtn.enabled)
				return ;
				
			mCurrentDialogMenu.y -= (mCurrentDialogMenu.optionHeight + mCurrentDialogMenu.separatorY+ mMenuOffsetY) ;
			UpdateScrollButtons();
		}
		
				/**
		 * @private 
		 */
		protected function CreateUpArrow():WakSimpleButton
		{
			var fBtn:WakSimpleButton = null 
			 
			var fUp:Sprite = DrawDownArrow(0x120012,0x8a348d);
			fUp.rotation = 180 ;
			fUp.x = fUp.width + 1; 
			fUp.y = fUp.height ;
			
			var fOver:Sprite = DrawDownArrow(0x120012,0x8a348d);
			fOver.rotation = 180 ;
			fOver.x = fUp.width + 1; 
			fOver.y = fUp.height ;
			
			var fDown:Sprite = DrawDownArrow(0x120012,0x8a348d);
			fDown.rotation = 180 ;
			fDown.x = fUp.width + 1; 
			fDown.y = fUp.height ;
			
			fBtn = new WakSimpleButton( fUp, fOver, fDown);
			fBtn.y = 2 ;
			fBtn.enabled = false ;
			return fBtn ;
		}
		
				/**
		 * @private 
		 */
		protected function CreateDownArrow():WakSimpleButton
		{
			var fUp:Sprite = DrawDownArrow(0x120012,0x8a348d);
			var fOver:Sprite = DrawDownArrow(0x120012,0x8a348d);
			var fDown:Sprite = DrawDownArrow(0x120012,0x8a348d);
			var fBtn:WakSimpleButton = new WakSimpleButton(fUp,fOver,fDown);
			
			fBtn.y = fBtn.height + 2 ;
			fBtn.enabled = false ;
			return fBtn;
			  
		}
		
		/**
		 * @private 
		 */		
		protected function DrawDownArrow(pBgColor:uint, pArrowColor:uint):Sprite
		{
			var fArrow:Sprite = new Sprite();
			fArrow.graphics.beginFill(pBgColor);
			fArrow.graphics.drawRect(0,0,26,44);
			fArrow.graphics.endFill();
			
			fArrow.graphics.lineStyle(1,pArrowColor);
			fArrow.graphics.moveTo(9,2);
			fArrow.graphics.lineTo(9,25);
			
			fArrow.graphics.moveTo(9,25);
			fArrow.graphics.lineTo(1,25);
			
			fArrow.graphics.moveTo(1,25);
			fArrow.graphics.lineTo(13,38);
			
			fArrow.graphics.moveTo(13,38);
			fArrow.graphics.lineTo(26,25);
			
			fArrow.graphics.moveTo(26,25);
			fArrow.graphics.lineTo(18,25);
			
			fArrow.graphics.moveTo(18,25);
			fArrow.graphics.lineTo(18,2);
			
			fArrow.graphics.moveTo(18,2);
			fArrow.graphics.lineTo(9,2);
			fArrow.graphics.endFill();
			
			return fArrow ;
			
		}
		
		/**
		 * @inheritDoc 
		 * 
		 */		
		public function DisplayInfo(pText:String, pOnCompleteFunction:Function = null ):void
		{
			var fNewText:DialogTextDisplay = new DialogTextDisplay(pText,GetTextTime(pText),
											mDialogLayer, null,mSpokenTextFont,
											mSpokenTextSize,mDisplayInfoColor,mSpokenTextBold, mSpokenTextUseEmbedFont);
			if(pOnCompleteFunction != null)			
				fNewText.addEventListener(Event.COMPLETE,pOnCompleteFunction,false,0,true);
			fNewText.clickEndEnabled = true ;
			mDialogLayer.addChild(fNewText);
			//trace("fNewText.width:"+fNewText.width);
			fNewText.x =  mStageWidth / 2 ;
			fNewText.y = mDisplayInfoY;
		}
		
		public function SetOptionVisible(pDialogId:String, pTopicId:String, value:Boolean):void
		{
			CreateDialogMenu(pDialogId);
			var fDMenu:DialogMenu = mDialogsMenuArray[pDialogId] ;
			if(fDMenu == null)
			{
				return ;
			}
			
			fDMenu.SetOptionVisible(pTopicId,value);
			UpdateScrollButtons();
		}
		
		
	}
}